/*
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted.
 *
 * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
module mlib.term;

import std.typecons : Flag;
public import std.typecons : Yes, No;

public class Term
{
   import std.stdio : stderr, stdout;

   static void clearCurrentLine(Flag!"useStderr" useStderr = No.useStderr)
   {
      if (useStderr) {
         stderr.writef("\r\033[2K");
         stderr.flush();
      } else {
         stdout.writef("\r\033[2K");
         stdout.flush();
      }
   }

   private static extern(C) void handleInterrupt(int) @nogc nothrow
   {
       import core.stdc.stdlib : exit;
       import core.stdc.stdio : stderr, fputs;

       fputs("\r\033[2K\033[?25h", stderr);
       exit(1);
   }

   static void disableCursor()
   {
       import core.stdc.signal;
       import core.stdc.stdio : fputs, stderr;

       signal(SIGINT, &handleInterrupt);
       signal(SIGTERM, &handleInterrupt);
       fputs("\033[?25l", stderr);
   }

   static void enableCursor()
   {
      import core.stdc.signal;
      import core.stdc.stdio : fputs, stderr;

      signal(SIGINT, SIG_DFL);
      signal(SIGTERM, SIG_DFL);
      fputs("\033[?25h", stderr);
   }

   /// Return the number of columns for the current terminal.
   static ushort getColumnCount()
   {
      return getColumnCountImpl();
   }

   static void goUpAndClearLine(int lines, Flag!"useStderr" useStderr = No.useStderr)
   {
      if (useStderr) {
         stderr.writef("\033[%dF\033[2K", lines);
         stderr.flush();
      } else {
         stdout.writef("\033[%dF\033[2K", lines);
         stdout.flush();
      }
   }
}

version (Posix)
{

   ushort getColumnCountImpl()
   {
      import core.sys.posix.sys.ioctl : winsize, TIOCGWINSZ, ioctl;
      import core.sys.posix.unistd : STDOUT_FILENO;

      winsize w;
      ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
      return w.ws_col;
   }

}
